/* Copyright (c) 1998, 2011, Oracle and/or its affiliates. 
All rights reserved. */


This file is the README file for sample programs in the SQLJ demo directory.
It specifies the steps required to run each of the programs in this directory,
and their expected behavior.  All demos use the scott/tiger schema.

We also provide a makefile for running the samples, which you may be able to
use.  Type 'make' to get usage information.  In this README, we give the
individual steps to run each sample program without using the makefile.

The programs in the demo directory all use information contained in the 
file "connect.properties" to establish a runtime connection.  Verify that
the "sqlj.url", "sqlj.user", and "sqlj.password" entries of this file
reflect the logon strings used for your JDBC driver and database account.


0. First, Check Your Environment Setup
**************************************

Make sure that the SQLJ translator utility can be invoked from the command
line prompt, and produces the expected output:

% sqlj
Usage:  sqlj [options] file1.sqlj [file2.java] ...
   or   sqlj [options] file1.ser  [file2.jar]  ...
where options include:
     -d=<directory>           root directory for generated binary files
     -encoding=<encoding>     Java encoding for source files
     -user=<user>/<password>  enable online checking
     -url=<url>               specify URL for online checking
     -status                  print status during translation
     -compile=false           do not compile generated Java files
     -linemap                 instrument compiled class files from sqlj source
     -profile=false           do not customize generated *.ser profile files
     -ser2class               convert generated *.ser files to *.class files
     -P-<option> -C-<option>  pass -<option> to profile customizer or compiler
     -P-help  -C-help         get help on profile customizer or compiler
     -J-<option>              pass -<option> to the JavaVM running SQLJ
     -version                 get SQLJ version
     -help-alias              get help on command-line aliases
     -help-long               get full help on all front-end options

Note:  place -<key>=<value> in sqlj.properties as sqlj.<key>=<value>


If this expected output is not obtained, please check your environment settings
for PATH and CLASSPATH:
   * PATH should include the directory .../sqlj/bin
   * CLASSPATH should include the file .../sqlj/lib/translator.jar
   * CLASSPATH should include the file .../sqlj/lib/runtime.jar
     (If you use JDBC 8.1.7 you can also use use runtime11.jar or
      runtime12.jar, depending on your JDK version.)
In addition, a JDK 1.1-compatible Java compiler (assumed to be javac) and the
java interpreter (assumed java) must be correctly installed.

Note that the SQLJ runtime classes are packaged separately as
.../sqlj/lib/runtime.jar (or runtime11.jar, runtime12.jar), and can be
used to execute a previously-translated SQLJ program.
The runtime classes are _not_ included in translator.jar (unlike in
previous versions of SQLJ).


1. Samples for Testing Your Database Setup 
******************************************

There are four relevant programs that test basic JDBC and SQLJ connections to
the database account scott/tiger:

1.1. TestInstallCreateTable.java
================================
   
This JDBC program creates a table named 'SALES' in the schema for user SCOTT.
This table is used in the other three TestInstall programs (1.2, 1.3 and 1.4).

The following commands will compile and run this program:

% javac TestInstallCreateTable.java
% java  TestInstallCreateTable

Expected output on the screen is:

SALES table created

and the table should be present in the scott/tiger database account.  

A related file is TestInstall.sql.  This file contains a SQL script to create
the same 'SALES' table via SQL*Plus.


1.2. TestInstallJDBC.java
=========================

This is another program that verifies your JDBC setup.  It uses the SALES table
created by the previous program, TestInstallCreateTable.java, in user SCOTT's
schema.

The following commands will compile and run this sample:

% javac TestInstallJDBC.java
% java  TestInstallJDBC

Expected output to the screen is:

Hello JDBC!


1.3. TestInstallSQLJ.sqlj
=========================

This is a basic SQLJ program to check the SQLJ translator and runtime setup.
The following commands will translate, compile and run it:

% sqlj TestInstallSQLJ.sqlj
% java TestInstallSQLJ

Expected output to the screen is:

Hello, SQLJ!

No changes are committed to the database, since autocommit is false by default
for the connection established through the Oracle.connect() call.  Note that
this is behavior is different from the JDBC drivers, which have autocommit
turned on by default.


1.4. TestInstallSQLJChecker.sqlj
================================

This sample tests online translation, where the SQLJ translator connects to the
database during translation, and verifies static SQL statements in your code.

The URL, user, and password for the database account to be used by the SQL
checker is provided in the sqlj.properties.  In particular, the following
lines in sqlj.properties are relevant for online checking of this program:


-----------------  fragment of sqlj.properties ------------------

### turn on checking by uncommenting user 
### or specifying the -user option on the command line
#sqlj.user=scott
sqlj.password=tiger

### add additional drivers here
#sqlj.driver=oracle.jdbc.driver.OracleDriver<,driver2...>

### Oracle JDBC-OCI7 URL
#sqlj.url=jdbc:oracle:oci7:@

### Oracle JDBC-OCI8 URL
#sqlj.url=jdbc:oracle:oci8:@

### Oracle JDBC-Thin URL
#sqlj.url=jdbc:oracle:thin:@<host>:<port>:<oracle_sid>
#sqlj.url=jdbc:oracle:thin:@localhost:1521:orcl

----------------------- end fragment ------------------------


As noted in the above fragment from sqlj.properties file, uncomment the line

#sqlj.user=scott

to turn on online checking.   Alternatively, the -user option can be specified 
on the sqlj command line, as follows:

% sqlj -user=scott/tiger TestInstallSQLJChecker.sqlj

The -user option need not be provided if it is already specified in the
sqlj.properties file.

Expected translation output to the screen is:

TestInstallSQLJChecker.sqlj:54.5-54.48: Error: Unable to check SQL query. 
Error returned by database is: ORA-00904: invalid column name

Total 1 error.

This error has been intentionally introduced in the program to illustrate
the SQL checking functionality of the SQLJ translator.  To fix this error,
replace the string "ITEM_NAMAE" in line 54 of the program file
TestInstallSQLJChecker.sqlj with "ITEM_NAME".  Once this step is done, you
can re-translate and run the program as follows:

% sqlj -user=scott/tiger TestInstallSQLJChecker.sqlj
% java TestInstallSQLJChecker

Expected runtime output to the screen is:

Hello, SQLJ Checker!


2. Samples on Querying SQL Data
*******************************

There are four sample programs in this area:

2.1  NamedIterDemo.sqlj 
=======================

This sample illustrates retrieval of multi-row data through named iterators on
the SALES table in the scott/tiger schema.  The SALES table can be created
either by executing the sample program TestInstallCreateTable.java or by using
the SQL script TestInstall.sql (see section 1.1 in this README file).

This sample can be translated and run as follows:

% sqlj NamedIterDemo.sqlj  
% java NamedIterDemo

  Note: if you compile this example under JDK1.2 you will get a deprecation
  warning.  To see the deprecation message you need to pass the -deprecation
  option to the Java compiler by prefixing it with -C as follows:
  % sqlj -C-deprecation NamedIterDemo.sqlj  

Expected runtime output on the screen is:


Running the example.

ITEM ID: 101
ITEM NAME: Relativistic redshift recorder
COST: 10999.95
SALES DATE: 1997-10-22
SALES REP ID: 1
SALES REP NAME: John Smith          

ITEM ID: 1001
ITEM NAME: Left-handed hammer            
COST: 79.99
SALES DATE: 1997-12-06
SALES REP ID: 358
SALES REP NAME: Jouni Seppanen   


However, no rows are committed in SALES table, since autocommit is false by
default for the connection established through the Oracle.connect() call.  Note
that this is behavior is different from the JDBC drivers, which have autocommit
turned on by default.  To make the changes permanent in the database, add
   #sql { commit };
after the updates. 


For online SQL checking during translation, use either the -user=scott option
on the command-line or uncomment the #sqlj.user=scott line in the
sqlj.properties file.

% sqlj  -user=scott/tiger NamedIterDemo.sqlj  

In this mode, the expected output of translation is:

NamedIterDemo.sqlj:129.5-130.54: Warning: The column int item_number is not 
nullable, even though it may be NULL in the select list. This may result in 
a runtime error.
NamedIterDemo.sqlj:129.5-130.54: Warning: Loss of precision possible in 
conversion from NUMERIC to column int item_number.
NamedIterDemo.sqlj:127.5-130.54: Warning: The column double cost is not 
nullable, even though it may be NULL in the select list. This may result 
in a runtime error.
NamedIterDemo.sqlj:129.5-130.54: Warning: Loss of precision possible in 
conversion from NUMERIC to column double cost.
NamedIterDemo.sqlj:129.5-130.54: Warning: Loss of precision possible in 
conversion from NUMERIC to column java.lang.Integer sales_rep_number.
Total 5 warnings.


These warnings show precision and nullability issues with fetching SQL data
into Java types.  You can eliminate these warnings with the following 
setting of the -warn flag.

% sqlj  -user=scott/tiger -warn=nonulls,noprecision NamedIterDemo.sqlj  


2.2  PosIterDemo.sqlj 
=====================

This sample illustrates retrieval of multi-row data through positional
iterators on the SALES table in the scott/tiger schema.  The SALES table can be
created either by executing the sample program TestInstallCreateTable.java or
by using the SQL script TestInstall.sql (see section 1.1 in this README file).

The program also demonstrates the use of explicit connection contexts, by
declaring a SQLJ connection context class named PosIterDemoCtx and using 
instances of this connection context type in #sql statements.

The sample can be translated and run as follows:

% sqlj PosIterDemo.sqlj  
% java PosIterDemo

Expected runtime output on the screen is:


Sales records before delete
ITEM NUMBER: 250
ITEM NAME: widget1                       
SALES DATE: 1997-10-09
COST: 12.0

ITEM NUMBER: 267
ITEM NAME: thing1                        
SALES DATE: 1997-10-10
COST: 700.0

ITEM NUMBER: 270
ITEM NAME: widget2                       
SALES DATE: 1997-10-10
COST: 13.0

Sales records after delete
ITEM NUMBER: 250
ITEM NAME: widget1                       
SALES DATE: 1997-10-09
COST: 12.0


However, no rows are committed in SALES table, since autocommit is false by
default for the connection established through the Oracle.connect() call.  Note
that this is behavior is different from the JDBC drivers, which have autocommit
turned on by default.  To make the changes permanent in the database, add
   #sql { commit };
after the updates. 


For online SQL checking during translation, use either the -user=scott option
on the command-line or uncomment the #sqlj.user=scott line in the
sqlj.properties file.  In this mode, the expected output of translation is:


PosIterDemo.sqlj:111.5-112.20: Warning: The column int #1 is not nullable, 
even though it may be NULL in the select list. This may result in a runtime 
error.
PosIterDemo.sqlj:111.5-112.20: Warning: Loss of precision possible in 
conversion from NUMERIC to column int #1.
PosIterDemo.sqlj:111.5-112.20: Warning: The column double #4 is not nullable,
even though it may be NULL in the select list. This may result in a runtime 
error.
PosIterDemo.sqlj:111.5-112.20: Warning: Loss of precision possible in 
conversion from NUMERIC to column double #4.
Total 4 warnings.

These warnings show precision and nullability issues with fetching SQL data
into Java types.


2.3  QueryDemo.sqlj
===================

This sample program demonstrates the various constructs that may be used to
fetch a row of data using SQLJ.  It also demonstrates the use of explicit and
default connection contexts.

This program uses the EMP and DEPT tables available by default in the
scott/tiger schema.  These tables can be recreated explicitly using the
SQL script emp.sql.  Additionally, this program requires that a PL/SQL
function named 'get_sal' be first defined in the scott/tiger schema.  The
SQL script QueryDemo.sql is provided for this purpose.

The sample can be translated and run as follows:

% sqlplus scott/tiger @QueryDemo.sql
% sqlj QueryDemo.sqlj  
% java QueryDemo SCOTT 5000

Expected runtime output on the screen is:

before update:
salary of SCOTT is 3000.0
salary of SCOTT is 3000.0
after update:
salary of SCOTT is 5000.0
salary of SCOTT is 5000.0


The database is not actually modified, since autocommit is false by default for
the connection established through the Oracle.connect() call.  Note that this
is behavior is different from the JDBC drivers, which have autocommit turned on
by default.  To make your changes permanent in the database, use
   #sql { commit };
after the updates. 


For online SQL checking during translation, you can either use the -user=scott
option on the command-line or uncomment the #sqlj.user=scott line in the
sqlj.properties file.  If desired, QueryDemoCtx can be made to point to a
different schema/database - simply modify the lines of QueryDemoCtx in
sqlj.properties file to appropriately reflect your connection information, or
specify them on the sqlj command line.

In the online mode, the expected output of translation is:

sqlj -user=scott QueryDemo.sqlj

QueryDemo.sqlj:63.5-63.73: Warning: The column double sal is not nullable, even
though it may be NULL in the select list. This may result in a runtime error.
QueryDemo.sqlj:74.5-74.67: Warning: The column double #1 is not nullable, even
though it may be NULL in the select list. This may result in a runtime error.
QueryDemo.sqlj:101.5-101.63: Warning: The column double #1 is not nullable, even
though it may be NULL in the select list. This may result in a runtime error.
Total 3 warnings.

These warnings show precision and nullability issues with fetching SQL data
into Java types.

If online translation gives the following additional warning:

QueryDemo.sqlj:93.5-93.48: Warning: Cannot determine default arguments for 
stored procedures and functions. May need to install SYS.SQLJUTL.

it indicates that you will need to install the sqljutl.sql script in the
SYS schema on your database.  This script is available under
   .../sqlj/lib/sqljutl.sql


2.4  SubclassIterDemo.sqlj 
==========================

This sample illustrates the potential in using subclassing of SQLJ
iterators to achieve more complex behavior.  In this example we
construct an Emp object out of each of the retrieved rows and insert
these objects into a Vector.  The vector can then be used and processed
separately.

This sample can be translated and run as follows:

% sqlj SubclassIterDemo.sqlj  
% java SubclassIterDemo

Expected runtime output on the screen is:

Running the example.

EMP SMITH has ID 7369
EMP ALLEN has ID 7499
EMP WARD has ID 7521
EMP JONES has ID 7566
EMP MARTIN has ID 7654
EMP BLAKE has ID 7698
EMP CLARK has ID 7782
EMP SCOTT has ID 7788
EMP KING has ID 7839
EMP TURNER has ID 7844
EMP ADAMS has ID 7876
EMP JAMES has ID 7900
EMP FORD has ID 7902
EMP MILLER has ID 7934


3.  Sample on Host Expressions
******************************

There is one sample application in this area:

3.1  ExprDemo.sqlj
==================

This sample program shows the use of Java host expressions in #sql statements
for passing arguments into and out of SQL operations.  

The program can be translated and run as follows:

% sqlj ExprDemo.sqlj
% java ExprDemo

Expected output on the screen is:

Running the example.

array[0..5] = { 1000,1001,1,1003,1004,1005, }

array[0..5] = { 1000,1001,1,1003,1004,1005, }

obj.field = 2

indx = 100
total = 1

indx = 2
total = 100

integer = null


For online SQL checking during translation, use either the -user=scott option
on the command-line or uncomment the #sqlj.user=scott line in the
sqlj.properties file.  In this mode, the expected output of translation is:

ExprDemo.sqlj:120.5-120.59: Warning: The column int #1 is not nullable, even 
though it may be NULL in the select list. This may result in a runtime error.
ExprDemo.sqlj:120.5-120.59: Warning: Loss of precision possible in conversion
from NUMERIC to column int #1.
ExprDemo.sqlj:157.5-157.68: Warning: The column int #1 is not nullable, even
though it may be NULL in the select list. This may result in a runtime error.
ExprDemo.sqlj:157.5-157.68: Warning: Loss of precision possible in conversion
from NUMERIC to column int #1.
ExprDemo.sqlj:157.5-157.68: Warning: The column int #2 is not nullable, even
though it may be NULL in the select list. This may result in a runtime error.
ExprDemo.sqlj:157.5-157.68: Warning: Loss of precision possible in conversion
from NUMERIC to column int #2.
Total 6 warnings.

These warnings show precision and nullability issues with fetching SQL data
into Java types.

In fact, the translation and running result above shows that Oracle-specific code generation (the default setting for -codegen) does not handle side-effects during expression evaluation, but rather assumes that expressions are free of side effect. The following translation and running results show that the generci code generator can deal with side-effects:

% sqlj -codegen=iso ExprDemo.sqlj
% java ExprDemo

Expected output on the screen is:

Running the example.

array[0..5] = { 1000,1001,1,1003,1004,1005, }

array[0..5] = { 1000,1,1002,1003,1004,1005, }

obj.field = 2

indx = 100
total = 1

indx = 2
total = 100

integer = null

4. Sample on Multiple Schemas/Connections
*****************************************

In addition to the samples PosIterDemo.sql and QueryDemo.sqlj, there is one 
other sample program in this area:

4.1  MultiSchemaDemo.sqlj
=========================

This program uses the EMP and DEPT tables available by default in the
scott/tiger schema.  These tables can be recreated explicitly using the
SQL script emp.sql.

The sample can be translated and run as follows:

% sqlj MultiSchemaDemo.sqlj
% java MultiSchemaDemo

Expected runtime output on the screen is:

employee: SMITH, department: RESEARCH
employee: ALLEN, department: SALES
employee: WARD, department: SALES
employee: JONES, department: RESEARCH
employee: MARTIN, department: SALES
employee: BLAKE, department: SALES
employee: CLARK, department: ACCOUNTING
employee: SCOTT, department: RESEARCH
employee: KING, department: ACCOUNTING
employee: TURNER, department: SALES
employee: ADAMS, department: RESEARCH
employee: JAMES, department: SALES
employee: FORD, department: RESEARCH
employee: MILLER, department: ACCOUNTING


For online SQL checking during translation, you can either use the -user=scott
option on the command-line or uncomment the #sqlj.user=scott line in the
sqlj.properties file.  If desired, DeptCtx can be made to point to a different
schema/database by specifying the connection settings of DeptCtx either in the
sqlj.properties file or on the command-line, along the lines of the DemoCtx
context type used in sample program QueryDemo.sqlj (section 2.3 in this
README file).

In the online mode, the expected output of translation is:

sqlj -user=scott/tiger MultiSchemaDemo.sqlj

MultiSchemaDemo.sqlj:44.5-44.49: Warning: The column int deptno is not 
nullable, even though it may be NULL in the select list. This may result
in a runtime error.
Total 1 warning.


This warning shows a possible data-dependent runtime error in fetching nullable
SQL data into a Java scalar type.  The warning may be eliminated by using a
Java object type such as Integer instead of the scalar type int for the column
deptno in the Employees iterator.  This is left as an exercise for the user.



5. Sample on Multi-threaded application
***************************************

5.1 MultiThreadDemo.sqlj
========================

This program illustrates the use of multiple threads in a SQLJ program, each of
which performs some database operation.  Since all threads use the same default
connection context, each #sql statement uses an explicit execution context
instance to avoid conflict at runtime.

This program uses the EMP and DEPT tables available by default in the
scott/tiger schema.  These tables can be recreated explicitly using the
SQL script emp.sql.

This sample can be translated and run as follows:

% sqlj MultiThreadDemo.sqlj
% java MultiThreadDemo

Expected output on the screen at runtime differs depending on which thread
runs first.  It is either:

Gave raise of 250.5 to 14 employees
Gave raise of 150.5 to 14 employees
average salary change: 401.0

or: 

Gave raise of 150.5 to 14 employees
Gave raise of 250.5 to 14 employees
average salary change: 401.0

The database is not actually modified, since autocommit is false by default for
the connection established through the Oracle.connect() call.  Note that this
is behavior is different from the JDBC drivers, which have autocommit turned on
by default.


For online SQL checking during translation, use either the -user=scott option
on the command-line or uncomment the #sqlj.user=scott line in the
sqlj.properties file.  In this mode, the expected output of translation is:

MultiThreadDemo.sqlj:45.5-45.47: Warning: The column double #1 is not nullable,
even though it may be NULL in the select list. This may result in a runtime 
error.
MultiThreadDemo.sqlj:45.5-45.47: Warning: Loss of precision possible in 
conversion from NUMERIC to column double #1.
Total 2 warnings.

These warnings show precision and nullability issues with fetching SQL data
into Java types.



6.  Sample program for dynamic SQL/JDBC Interoperability
********************************************************

The program PrefetchDemo.sqlj in section 7.1 also demonstrates some JDBC
interoperability.

The following is the main sample in this area:

6.1 JDBCInteropDemo.sqlj 
========================

This sample illustrates the use of dynamic SQL via JDBC in a SQLJ program.

This program uses the EMP and DEPT tables available by default in the
scott/tiger schema.  These tables can be recreated explicitly using the
SQL script emp.sql.

The program can be translated and run as follows:

% sqlj JDBCInteropDemo.sqlj 
% java JDBCInteropDemo  "sal > 2000"

Expected output at runtime is :

JONES earns 2975.0
BLAKE earns 2850.0
CLARK earns 2450.0
SCOTT earns 3000.0
KING earns 5000.0
FORD earns 3000.0
 

Online checking is not useful for this program, since it uses dynamic SQL
in JDBC to perform the query. 



7.  Sample Program for REF Cursors
**********************************

There is one sample in this area:

7.1 RefCursDemo.sqlj
====================


This sample program demonstrates various ways a REF Cursor may be used 
in a SQLJ program. 

This program uses the EMP and DEPT tables available by default in the
scott/tiger schema.  These tables can be recreated explicitly using the SQL
script emp.sql.  Additionally, this program requires that a PL/SQL package
named 'SQLJRefCursDemo' be first defined in the scott/tiger schema.  The
SQL script RefCursDemo.sql is provided for this purpose.

The sample can be translated and run as follows:

% sqlplus scott/tiger @RefCursDemo.sql
% sqlj RefCursDemo.sqlj  
% java RefCursDemo 

Expected runtime output on the screen is:

Using anonymous block for ref cursor..
Employee list:
         Employee name: SMITH, id : 7369
         Employee name: ALLEN, id : 7499
         Employee name: WARD, id : 7521
         Employee name: JONES, id : 7566
         Employee name: MARTIN, id : 7654
         Employee name: BLAKE, id : 7698
         Employee name: CLARK, id : 7782
         Employee name: SCOTT, id : 7788
         Employee name: KING, id : 7839
         Employee name: TURNER, id : 7844
         Employee name: ADAMS, id : 7876
         Employee name: JAMES, id : 7900
         Employee name: FORD, id : 7902
         Employee name: MILLER, id : 7934
         Employee name: Joe Doe, id : 8100

Using stored procedure for ref cursor..
Employee list:

         Employee name: SMITH, id : 7369
         Employee name: ALLEN, id : 7499
         Employee name: WARD, id : 7521
         Employee name: JONES, id : 7566
         Employee name: MARTIN, id : 7654
         Employee name: BLAKE, id : 7698
         Employee name: CLARK, id : 7782
         Employee name: SCOTT, id : 7788
         Employee name: KING, id : 7839
         Employee name: TURNER, id : 7844
         Employee name: ADAMS, id : 7876
         Employee name: JAMES, id : 7900
         Employee name: FORD, id : 7902
         Employee name: MILLER, id : 7934
         Employee name: Joe Doe, id : 8100
         Employee name: Jane Doe, id : 8200

Using stored procedure for ref cursor..
Employee list:
         Employee name: SMITH, id : 7369
         Employee name: ALLEN, id : 7499
         Employee name: WARD, id : 7521
         Employee name: JONES, id : 7566
         Employee name: MARTIN, id : 7654
         Employee name: BLAKE, id : 7698
         Employee name: CLARK, id : 7782
         Employee name: SCOTT, id : 7788
         Employee name: KING, id : 7839
         Employee name: TURNER, id : 7844
         Employee name: ADAMS, id : 7876
         Employee name: JAMES, id : 7900
         Employee name: FORD, id : 7902
         Employee name: MILLER, id : 7934
         Employee name: Joe Doe, id : 8100
         Employee name: Jane Doe, id : 8200
         Employee name: Bill Smith, id : 8300


The database is not actually modified, since autocommit is false by default for
the connection established through the Oracle.connect() call.  Note that this
is behavior is different from the JDBC drivers, which have autocommit turned on
by default.  To make your changes permanent in the database, use
   #sql { commit };
after the updates. 


For online SQL checking during translation, you can either uncomment the
#sqlj.user=scott line in the sqlj.properties file, or use the -user=scott
option on the command-line (the password 'tiger' is in the sqlj.properties
file), as follows:

sqlj -user=scott RefCursDemo.sqlj


8.  Sample program for using dynamic SQL in SQLJ
************************************************

There is one sample in this area:

8.1 DynamicDemo.sqlj
====================

This sample program demonstrates various ways for programming dynamic SQL
statements in a SQLJ program:

- using dynamic SQLJ statements available in Oracle SQLJ version 9i and
  later.  This is the most concise way to write dynamic SQL statements.

- using PL/SQL blocks to construct and execute dynamic SQL statements

- inter-operating with JDBC to execute dynamic SQL statements

This program creates its own tables: EMP_SQLJ, EMP_PL_SQL, and EMP_JDBC
(in a dynamic fashion, of course) and then performs various DDL, DML,
and queries on these tables.

The sample can be translated and run as follows:

% sqlj DynamicDemo.sqlj
% java DynamicDemo

Expected output at runtime is :

*** Demo of using dynamic SQL through SQLJ ***
Dropping table emp_SQLJ
Creating table emp_SQLJ and index sal_emp_SQLJ on column sal
Dynamic insert on table emp_SQLJ of employee julie
Dynamic insert on table emp_SQLJ of employee scott
Dynamic insert on table emp_SQLJ of employee king
Dynamic insert on table emp_SQLJ of employee adams
Dynamic delete of empno = 8455 or empno is null
Dynamic update-returning in table emp_SQLJ for empno 7788
Updated the salary of employee scott
Dynamic 1-row query on table emp_SQLJ
Number of rows in table emp_SQLJ is 3
Dynamic multi-row query on table emp
Employee king has salary 4500.0
Employee scott has salary 7000.0
Dynamic multi-row query on table emp
Employee adams has salary 1900.0
Employee king has salary 4500.0
Employee scott has salary 7000.0
*** Demo of using dynamic SQL through PL_SQL ***
Dropping table emp_PL_SQL
Creating table emp_PL_SQL and index sal_emp_PL_SQL on column sal
Dynamic insert on table emp_PL_SQL of employee julie
Dynamic insert on table emp_PL_SQL of employee scott
Dynamic insert on table emp_PL_SQL of employee king
Dynamic insert on table emp_PL_SQL of employee adams
Dynamic delete of empno = 8455 or empno is null
Dynamic update-returning in table emp_PL_SQL for empno 7788
Updated the salary of employee scott
Dynamic 1-row query on table emp_PL_SQL
Number of rows in table emp_PL_SQL is 3
Dynamic multi-row query on table emp
Employee king has salary 4500.0
Employee scott has salary 7000.0
Dynamic multi-row query on table emp
Employee adams has salary 1900.0
Employee king has salary 4500.0
Employee scott has salary 7000.0
*** Demo of using dynamic SQL through JDBC ***
Dropping table emp_JDBC
Creating table emp_JDBC and index sal_emp_JDBC on column sal
Dynamic insert on table emp_JDBC of employee julie
Dynamic insert on table emp_JDBC of employee scott
Dynamic insert on table emp_JDBC of employee king
Dynamic insert on table emp_JDBC of employee adams
Dynamic delete of empno = 8455 or empno is null
Dynamic update-returning in table emp_JDBC for empno 7788
Updated the salary of employee scott
Dynamic 1-row query on table emp_JDBC
Number of rows in table emp_JDBC is 3
Dynamic multi-row query on table emp
Employee king has salary 4500.0
Employee scott has salary 7000.0
Dynamic multi-row query on table emp
Employee adams has salary 1900.0
Employee king has salary 4500.0
Employee scott has salary 7000.0



9.  Sample programs for Performance
***********************************

There are three samples in this area:

9.1 PrefetchDemo.sqlj 
=====================

This sample illustrates the use of row prefetching in SQLJ and JDBC.
It also shows interoperability with JDBC in order to exploit batch
INSERTs and UPDATEs.

This program uses the PREFETCH_DEMO table in the scott/tiger schema.
This table must be created first by running the SQL script PrefetchDemo.sql

% sqlplus scott/tiger @PrefetchDemo.sql
(you need to exit from sqlplus once this script has run)

The program can be translated and run as follows:

% sqlj PrefetchDemo.sqlj 
% java PrefetchDemo

Expected output at runtime is :

*** Start of Prefetch demo ***
Connected.
>>> Inserting data into the PREFETCH_DEMO table <<<
JDBC BATCHED: INSERT 1000 rows. Done in X.XXX seconds.
>>> Selecting data from the PREFETCH_DEMO table <<<
Default Row Prefetch value is:  10
JDBC: SELECT using row prefetch 1. Done in X.XXX seconds.
SQLJ: SELECT using row prefetch 1. Done in X.XXX seconds.
JDBC: SELECT using row prefetch 10. Done in X.XXX seconds.
SQLJ: SELECT using row prefetch 10. Done in X.XXX seconds.
JDBC: SELECT using row prefetch 100. Done in X.XXX seconds.
SQLJ: SELECT using row prefetch 100. Done in X.XXX seconds.
JDBC: SELECT using row prefetch 1000. Done in X.XXX seconds.
SQLJ: SELECT using row prefetch 1000. Done in X.XXX seconds.

The actual numbers X.XXX that you see will depend on your platform
and database configuration.  You should see better performance with
higher row prefetch values.  However, you will also notice diminishing
returns as the row prefetch value is increased.
Note also that the PREFETCH_DEMO table is not a very typical table,
since it only consists of a single numeric column.

For online SQL checking during translation, use either the -user=scott option
on the command-line or uncomment the #sqlj.user=scott line in the
sqlj.properties file.  In this mode, the expected output of translation is:

PrefetchDemo.sqlj:136.16-136.55: Warning: The column int n is not nullable,
even though it may be NULL in the select list. This may result in a runtime
error.
PrefetchDemo.sqlj:136.16-136.55: Warning: Loss of precision possible in
conversion from NUMERIC(38) to column int n.
PrefetchDemo.sqlj:137.16-137.55: Warning: The column int n is not nullable,
even though it may be NULL in the select list. This may result in a runtime
error.
PrefetchDemo.sqlj:137.16-137.55: Warning: Loss of precision possible in
conversion from NUMERIC(38) to column int n.
PrefetchDemo.sqlj:138.16-138.55: Warning: The column int n is not nullable,
even though it may be NULL in the select list. This may result in a runtime
error.
PrefetchDemo.sqlj:138.16-138.55: Warning: Loss of precision possible in
conversion from NUMERIC(38) to column int n.
PrefetchDemo.sqlj:139.16-139.55: Warning: The column int n is not nullable,
even though it may be NULL in the select list. This may result in a runtime
error.
PrefetchDemo.sqlj:139.16-139.55: Warning: Loss of precision possible in
conversion from NUMERIC(38) to column int n.
PrefetchDemo.sqlj:140.16-140.55: Warning: The column int n is not nullable,
even though it may be NULL in the select list. This may result in a runtime
error.
PrefetchDemo.sqlj:140.16-140.55: Warning: Loss of precision possible in
conversion from NUMERIC(38) to column int n.
Total 10 warnings.


9.2 BatchDemo.sqlj 
==================

This sample illustrates the use of batching in SQLJ.

This program uses the BATCH_DEMO table in the scott/tiger schema.
This table should be created first by running the SQL script BatchDemo.sql

% sqlplus scott/tiger @BatchDemo.sql
(you need to exit from sqlplus once this script has run)

The program can be translated and run as follows:

% sqlj BatchDemo.sqlj 
% java BatchDemo

Expected output at runtime is :

*** Batch Demo ***
Connected.
>>> Inserting 100 records <<<<
Inserting one record at a time. Done in X.XXX seconds.
Inserting in batch of 10. Done in X.XXX seconds.
Inserting in batch of 100. Done in X.XXX seconds.
Inserting in batch of 1000. Done in X.XXX seconds.
>>> Inserting 1000 records <<<<
Inserting one record at a time. Done in X.XXX seconds.
Inserting in batch of 10. Done in X.XXX seconds.
Inserting in batch of 100. Done in X.XXX seconds.
Inserting in batch of 1000. Done in X.XXX seconds.
*** End of Demo ***

The actual numbers X.XXX that you see will depend on your platform
and database configuration.  You should see better performance with
higher batch size values.  However, you will also notice diminishing
returns, or even performance loss as the batch size is increased.
Note also that the BATCH_DEMO table may not be representative to a
typical table that might be used in your application.

For online SQL checking during translation, use either the -user=scott option
on the command-line or uncomment the #sqlj.user=scott line in the
sqlj.properties file.  No messages are expected during online translation.

9.3 DmsDemo.sqlj 
==================

This sample illustrates the use of SQL monitoring capability in SQLJ, 
introduced in 10i Beta 2.

Make sure the dms.jar file in the classpath:

% setenv CLASSPATH ${ORACLE_HOME}/dms/lib/dms.jar:${CLASSPATH}

Instrument the program as follows:

% sqlj -dir=. -instrument=tmp.dmsdemo.app -components=all  -user=scott/tiger DmsDemo.sqlj

Run the instrumented program. Note that JDK 1.4 is required to run an instrumented program.
% cp connect.properties tmp/dmsdemo
% /usr/local/packages/jdk1.4.1/bin/java tmp.dmsdemo.DmsDemo

Expected output at runtime is :
 *** BEGIN SQL Monitoring Demo ***
DmsDemo.
Run SELECCT.
Running SELECT INTO.
array[0..5] = { 1000,1001,1,1003,1004,1005, }
array[0..5] = { 1000,1001,1,1003,1004,1005, }
Running PL/SQL Block
indx = 2
total = 100
 Close SQLMonitor and Dump Monitoring Result into tmp/dmsdemo/app.mtr
 *** END SQL Monitoring Demo ***

Here is some statistics from the file tmp/dmsdemo/app.mtr:

        SQLString.value:        select OBJECT_NAME from all_objects statement SQL string
       120.5
        Execute.time:    52.0 msecs
        (Show that the total time spent on the SELECT query is 52 msecs)

       Iter
        Next.time:      1282 msecs
       (Show that the total time spent for the next() option is 1282 msecs)

Generated files from this demo:
  tmp/dmsdemo/DmsDemo.java
  tmp/dmsdemo/app.properties (SQL monitor property file)
  tmp/dmsdemo/app.mtr (statistics collected)
